package com.kelvem.saas.workbanch.core.manager.service;

import com.kelvem.saas.workbanch.core.base.BaseCriteria;
import com.kelvem.saas.workbanch.core.base.BaseService;
import com.kelvem.saas.workbanch.core.base.Page;
import com.kelvem.saas.workbanch.core.exception.SaasAssert;
import com.kelvem.saas.workbanch.core.exception.SaasException;
import com.kelvem.saas.workbanch.core.manager.dao.BizPageDao;
import com.kelvem.saas.workbanch.core.manager.dto.MenuDto;
import com.kelvem.saas.workbanch.core.manager.model.BizPageActionEntity;
import com.kelvem.saas.workbanch.core.manager.model.BizPageDomEntity;
import com.kelvem.saas.workbanch.core.manager.model.BizPageEntity;
import com.kelvem.saas.workbanch.core.manager.model.MetaTableEntity;
import com.kelvem.saas.workbanch.core.manager.request.BizPageQueryVo;
import com.kelvem.saas.workbanch.core.manager.request.MetaTableQueryVo;
import com.kelvem.saas.workbanch.security.shiro.CurrentUser;
import com.kelvem.saas.workbanch.core.system.model.SysUserEntity;
import com.kelvem.saas.workbanch.core.utils.DateUtil;
import com.kelvem.saas.workbanch.core.utils.EntityUtils;
import com.kelvem.saas.workbanch.fsm.dao.BaseDao;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 实体业务Service
 *
 * @author kelvem
 * @version 1.0
 */
@Service
@Slf4j
public class BizPageService extends BaseService<BizPageEntity, BizPageQueryVo> {

    @Resource
    private BizPageDao bizPageDao;

    @Resource
    private MetaTableService metaTableService;

    @Resource
    private BizPageActionService bizPageActionService;

    @Resource
    private BizPageDomService bizPageDomService;

    /**
     * 增加实体业务
     *
     * @param bizPage 实体业务信息
     * @return Long 主键
     */
    @Transactional(rollbackFor = Exception.class)
    public Long addBizPage(BizPageEntity bizPage) {

        log.info("BizPageService:addBizPage:start, bizPage=【{}】", bizPage);
        SaasAssert.notNull(bizPage);

        try {
            if (bizPage.getPageType() == null) {
                bizPage.setPageType("meta");
            }
            if (bizPage.getCreateTime() == null) {
                bizPage.setCreateTime(DateUtil.now());
            }
            if (bizPage.getUpdateTime() == null) {
                bizPage.setUpdateTime(DateUtil.now());
            }

            bizPageDao.insert(bizPage);
            Long bizPageId = bizPage.getId();

            // panel & dom & action 通过前端页面自动补齐
            log.info("BizPageService:addBizPage:end, bizPageId={}", bizPageId);

            return bizPageId;
        } catch (Exception e) {
            String msg = String.format("BizPageService:addBizPage:error, %s", e.getMessage());
            log.error(msg, e);
            throw new SaasException(msg);
        }
    }

    /**
     * 修改实体业务
     *
     * @param bizPage 实体业务信息
     * @return 更新记录数
     */
    @Transactional(rollbackFor = Exception.class)
    public int updateBizPage(BizPageEntity bizPage) {

        log.info("BizPageService:updateBizPage:start, bizPage=【{}】", bizPage);
        SaasAssert.notNull(bizPage);
        SaasAssert.notNull(bizPage.getId());

        try {
            int count = bizPageDao.updateById(bizPage);
            log.info("BizPageService:updateBizPage:end, count={}", count);
            return count;
        } catch (Exception e) {
            String msg = String.format("BizPageService:updateBizPage:error, %s", e.getMessage());
            log.error(msg, e);
            throw new SaasException(msg);
        }
    }

    /**
     * 删除实体业务
     *
     * @param bizPageId 实体业务id
     * @return 删除记录数
     */
    @Transactional(rollbackFor = Exception.class)
    public int deleteBizPage(Long bizPageId) {

        log.info("BizPageService:deleteBizPage:start, bizPageId={}", bizPageId);
        SaasAssert.notNull(bizPageId);

        try {
            int paramCount = this.bizPageDomService.deleteByBizPageId(bizPageId);
            log.info("BizPageService:deleteBizPage, paramCount={}", paramCount);

            int actionCount = this.bizPageActionService.deleteByBizPageId(bizPageId);
            log.info("BizPageService:deleteBizPage, actionCount={}", actionCount);

            int businessCount = bizPageDao.deleteById(bizPageId);
            log.info("BizPageService:deleteBizPage:end, businessCount={}", businessCount);
            return businessCount;
        } catch (Exception e) {
            String msg = String.format("BizPageService:deleteBizPage:error, %s", e.getMessage());
            log.error(msg, e);
            throw new SaasException(msg);
        }
    }

    /**
     * 查询实体业务分页数据
     *
     * @param bizPageQueryVo 查询用
     * @return Page<BizPageDto>
     */
    public Page<BizPageEntity> queryBizPagePage(BizPageQueryVo bizPageQueryVo) {

        log.info("BizPageService:queryBizPagePage:start, bizPageQueryVo=【{}】", bizPageQueryVo);
        SaasAssert.notNull(bizPageQueryVo);

        try {
            // BizPage的page
            Page<BizPageEntity> page = super.queryPage(bizPageQueryVo);

            // MetaTableList
            List<Long> ids = EntityUtils.toIds(page.getRecords(), "metaTableId");
            MetaTableQueryVo tableQueryVo = MetaTableQueryVo.builder().ids(ids).build();
            List<MetaTableEntity> tableList = metaTableService.queryMetaTableList(tableQueryVo);

            // merge
            Map<Long, String> tableMap = tableList.stream()
                    .collect(Collectors.toMap(
                            MetaTableEntity::getId,  // 使用getId()方法作为key
                            MetaTableEntity::getTableChName   // 名称作为value
                    ));
            for (BizPageEntity buf : page.getRecords()) {
                buf.setMetaTableName(tableMap.getOrDefault(buf.getMetaTableId(), ""));
            }

            log.info("BizPageService:queryBizPagePage:end, page.size={}", page.getRecords().size());
            return page;
        } catch (Exception e) {
            String msg = String.format("BizPageService:queryBizPagePage:error, %s", e.getMessage());
            log.error(msg, e);
            throw new SaasException(msg);
        }
    }

    /**
     * 查询实体业务列表数据
     *
     * @param bizPageQueryVo 查询用
     * @return List<BizPage>
     */
    public List<BizPageEntity> queryBizPageList(BizPageQueryVo bizPageQueryVo) {

        log.info("BizPageService:queryBizPageList:start, bizPageQueryVo=【{}】", bizPageQueryVo);
        SaasAssert.notNull(bizPageQueryVo);

        try {
            List<BizPageEntity> list = super.queryList(bizPageQueryVo);
            log.info("BizPageService:queryBizPageList:end, list.size={}", list.size());
            return list;
        } catch (Exception e) {
            String msg = String.format("BizPageService:queryBizPageList:error, %s", e.getMessage());
            log.error(msg, e);
            throw new SaasException(msg);
        }
    }

    /**
     * 根据id查询实体业务信息
     *
     * @param bizPageId 实体业务id
     * @return BizPage
     */
    public BizPageEntity getBizPageById(Long bizPageId) {

        log.info("BizPageService:getBizPageById:start, bizPageId={}", bizPageId);
        SaasAssert.notNull(bizPageId);

        try {
            BizPageEntity bizPage = bizPageDao.getBizPageById(bizPageId);

            // 获取metaTableIdList
            Set<Long> metaTableIdSet = bizPage.getBizPageDomList().stream()
                    .filter(dom -> "panel".equals(dom.getDomType()) || "dialog".equals(dom.getDomType()))
                    .map(BizPageDomEntity::getMetaTableId) // 提取每个DomNode的metaTableId
                    .filter(Objects::nonNull) // 过滤掉null值，如果需要的话
                    .collect(Collectors.toSet()); // 收集到Set中去重
            List<Long> metaTableIdList = new ArrayList<>(metaTableIdSet);

            MetaTableQueryVo metaTableQueryVo = MetaTableQueryVo.builder().ids(metaTableIdList).build();
            List<MetaTableEntity> metaTableEntityList = metaTableService.queryMetaTableList(metaTableQueryVo);

            // 将List转换为Map，键为uuid，值为MetaTableEntity对象
            Map<Long, MetaTableEntity> metaTableEntityMap = metaTableEntityList.stream()
                    .collect(Collectors.toMap(MetaTableEntity::getId, entity -> entity));
            bizPage.setMetaTableMap(metaTableEntityMap);

            /**
             * param
             */
            List<BizPageDomEntity> bizPageDomList = bizPage.getBizPageDomList();
//            Map<String, BizPageDomEntity> bizPageDomMap = new HashMap<>();
//            for (BizPageDomEntity bizPageDom: bizPageDomList) {
//                bizPageDomMap.put(bizPageDom.getColEnName() + "#" + bizPageDom.getTemplatePositionType(), bizPageDom);
//            }
//
//            List<MetaTableColumnEntity> metaTableColumnList = metaTable.getMetaTableColumnList();
//            List<BizPageDomEntity> bufList = new ArrayList<>();
//            for (MetaTableColumnEntity metaTableColumn:
//                    metaTableColumnList) {
//                if (bizPageDomMap.containsKey(metaTableColumn.getColEnName() + "#query")) {
//                    bufList.add(bizPageDomMap.get(metaTableColumn.getColEnName() + "#query"));
//                } else {
//                    BizPageDomEntity buf = new BizPageDomEntity();
//                    BeanUtils.copyProperties(metaTableColumn, buf);
//                    buf.setTemplatePositionType(TemplatePositionEnum.query.getCode());
//                    bufList.add(buf);
//                }
//                if (bizPageDomMap.containsKey(metaTableColumn.getColEnName() + "#column")) {
//                    bufList.add(bizPageDomMap.get(metaTableColumn.getColEnName() + "#column"));
//                } else {
//                    BizPageDomEntity buf = new BizPageDomEntity();
//                    BeanUtils.copyProperties(metaTableColumn, buf);
//                    buf.setTemplatePositionType(TemplatePositionEnum.column.getCode());
//                    bufList.add(buf);
//                }
//            }
            bizPage.setBizPageDomList(bizPageDomList);

            /**
             * action
             */
            List<BizPageActionEntity> bizPageActionList = bizPage.getBizPageActionList();
//            Map<String, BizPageActionEntity> bizPageActionMap = new HashMap<>();
//            for (BizPageActionEntity bizPageAction:
//                    bizPageActionList) {
//                bizPageActionMap.put(bizPageAction.getEventName() + "#" + bizPageAction.getTemplatePositionType(), bizPageAction);
//            }

//            List<MetaTableActionEntity> metaTableActionList = metaTable.getMetaTableActionList();
//            for (MetaTableActionEntity metaTableAction:
//                    metaTableActionList) {
//                String key = metaTableAction.getEventName() + "#" + metaTableAction.getTemplatePositionType();
//                if (!bizPageActionMap.containsKey(key)) {
//                    BizPageActionEntity buf = new BizPageActionEntity();
//                    BeanUtils.copyProperties(metaTableAction, buf);
//                    bizPageActionList.add(buf);
//                }
//            }
            bizPage.setBizPageActionList(bizPageActionList);
            log.info("BizPageService:getBizPageById:end, bizPageInfo=【{}】", bizPage);

            return bizPage;
        } catch (Exception e) {
            String msg = String.format("BizPageService:getBizPageById:error, %s", e.getMessage());
            log.error(msg, e);
            throw new SaasException(msg);
        }
    }

    /**
     * 构建查询用Criteria
     * 基类的queryPage, queryList方法使用
     *
     * @param queryVo 查询用
     * @return BaseCriteria
     */
    @Override
    public BaseCriteria<BizPageEntity> buildQueryCriteria(BizPageQueryVo queryVo) {
        BaseCriteria<BizPageEntity> criteria = new BaseCriteria<>();
        criteria.orderByAsc("sort_no", "id");

        // 主键
        Long id = queryVo.getId();
        if (super.isNotEmpty(id)) {
            criteria.andEqualTo("id", queryVo.getId());
        }

        // 创建时间
        Date startCreateTime = queryVo.getStartCreateTime();
        if(super.isNotEmpty(startCreateTime)) {
            criteria.andGreaterThanOrEqualTo("createTime", startCreateTime);
        }
        Date endCreateTime = queryVo.getEndCreateTime();
        if(super.isNotEmpty(endCreateTime)) {
            criteria.andLessThanOrEqualTo("createTime", endCreateTime);
        }

        // 实体表id
        Long metaTableId = queryVo.getMetaTableId();
        if (super.isNotEmpty(metaTableId)) {
            criteria.andEqualTo("metaTableId", metaTableId);
        }

        // 一级菜单
        String menu1 = queryVo.getMenu1();
        if (super.isNotEmpty(menu1)) {
            criteria.andEqualTo("menu1", menu1);
        }

        // 二级菜单
        String menu2 = queryVo.getMenu2();
        if (super.isNotEmpty(menu2)) {
            criteria.andEqualTo("menu2", menu2);
        }

        // 模板类型
        String templateType = queryVo.getTemplateType();
        if (super.isNotEmpty(templateType)) {
            criteria.andEqualTo("templateType", templateType);
        }

        // 创建人
        String createUid = queryVo.getCreateUid();
        if (super.isNotEmpty(createUid)) {
            criteria.andEqualTo("createUid", createUid);
        }

        // 更新人
        String updateUid = queryVo.getUpdateUid();
        if (super.isNotEmpty(updateUid)) {
            criteria.andEqualTo("updateUid", updateUid);
        }

        return criteria;
    }

    @Override
    public BaseDao<BizPageEntity> getDao() {
        return this.bizPageDao;
    }


    @Transactional(rollbackFor = Exception.class)
    public Long saveBizPage(BizPageEntity bizPage) {
        // todo merge bizPage

        List<BizPageDomEntity> origBizPageDomList = this.bizPageDomService.queryBizPageDomList(bizPage.getId());
        this.bizPageDomService.merge(origBizPageDomList, bizPage.getBizPageDomList());

        List<BizPageActionEntity> origBizPageActionList = this.bizPageActionService.queryBizPageActionList(bizPage.getId());
        this.bizPageActionService.merge(origBizPageActionList, bizPage.getBizPageActionList());

        return bizPage.getId();
    }

    /**
     * 根据token获取菜单列表
     *
     * @return 菜单dto列表
     */
    @Transactional(rollbackFor = Exception.class)
    public List<MenuDto> queryMenuByToken() {
        log.info("BizPageService:queryMenuByToken:start");
        List<BizPageEntity> bizPageEntityList = null;
        SysUserEntity currentUser = CurrentUser.get();
        if (currentUser.getUsername().equals("admin")) {
            // admin查询全部
            BizPageQueryVo bizPageQueryVo = BizPageQueryVo.builder().build();
            bizPageEntityList = this.queryBizPageList(bizPageQueryVo);

        } else {
            // 获取登录用户的所属组织id
            Long orgId = currentUser.getOrgId();
            SaasAssert.notNull(orgId);
            bizPageEntityList = this.bizPageDao.queryMenuByOrgId(orgId);
        }

        Map<String, MenuDto> menuLv1Map = new LinkedHashMap<>();

        for (BizPageEntity page : bizPageEntityList) {
            String menu1 = page.getMenu1();
            if (super.isEmpty(menu1)) {
                continue;
            }
            if (menuLv1Map.containsKey(menu1)) {
                continue;
            }
            MenuDto dto = new MenuDto(menu1);
            menuLv1Map.put(menu1, dto);
        }

        for (BizPageEntity page : bizPageEntityList) {
            if (menuLv1Map.containsKey(page.getMenu1())) {
                MenuDto menuLv1 = menuLv1Map.get(page.getMenu1());
                MenuDto menuLv2 = MenuDto.convert(page);
                menuLv1.getChildren().add(menuLv2);

                if (super.isEmpty(menuLv1.getIcon())) {
                    menuLv1.setIcon(menuLv2.getIcon());
                }
            }
        }
        log.info("BizPageService:queryMenuByToken:end");

        return new ArrayList<>(menuLv1Map.values());
    }
}
